;-----------------------------------------------------------------------------
; This file contains the startup code used by the ICCARM C compiler.
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; All code in the modules (except ?RESET) will be placed in the ICODE segment.
;
; $Revision: 1.1 $
;
;-----------------------------------------------------------------------------

;
; Naming covention of labels in this file:
;
;  ?xxx   - External labels only accessed from assembler.
;  __xxx  - External labels accessed from or defined in C.
;  xxx    - Labels local to one module (note: this file contains
;           several modules).
;  main   - The starting point of the user program.
;

;---------------------------------------------------------------
; Macros and definitions for the whole file
;---------------------------------------------------------------

; Mode, correspords to bits 0-5 in CPSR
MODE_BITS   DEFINE  0x1F        ; Bit mask for mode bits in CPSR
USR_MODE    DEFINE  0x10        ; User mode
FIQ_MODE    DEFINE  0x11        ; Fast Interrupt Request mode
IRQ_MODE    DEFINE  0x12        ; Interrupt Request mode
SVC_MODE    DEFINE  0x13        ; Supervisor mode
ABT_MODE    DEFINE  0x17        ; Abort mode
UND_MODE    DEFINE  0x1B        ; Undefined Instruction mode
SYS_MODE    DEFINE  0x1F        ; System mode


;---------------------------------------------------------------
; ?RESET
; Reset Vector.
; Normally, segment INTVEC is linked at address 0.
; For debugging purposes, INTVEC may be placed at other
; addresses.
; A debugger that honors the entry point will start the
; program in a normal way even if INTVEC is not at address 0.
;---------------------------------------------------------------


        MODULE  ?RESET
        COMMON  INTVEC:CODE:NOROOT(2)
        PUBLIC  __program_start
        EXTERN  ?cstartup
        EXTERN  irq_handler
        CODE32  ; Always ARM mode after reset
        org 0x00
__program_start
        ldr pc,=?cstartup   ; Absolute jump can reach 4 GByte
;       ldr b,?cstartup     ; Relative branch allows remap, limited to 32 MByte

undef_handler:     ldr pc,=undef_handler          ; 0x04
swi_handler:       ldr pc,=swi_handler            ; 0x08
prefetch_handler:  ldr pc,=prefetch_handler       ; 0x0c
data_handler:      ldr pc,=data_handler           ; 0x10
vec14_handler:     ldr pc,=vec14_handler          ; 0x14
                   ldr pc,=irq_handler            ; 0x18
fiq_handler:       ldr pc,=fiq_handler            ; 0x1c

        ; Constant table entries (for ldr pc) will be placed at 0x20
        org 0x20
        LTORG
;       ENDMOD  __program_start
                ENDMOD


;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
        MODULE  ?CSTARTUP

        RSEG    IRQ_STACK:DATA(2)
        RSEG    FIQ_STACK:DATA(2)
        RSEG    SVC_STACK:DATA:NOROOT(2)
        RSEG    CSTACK:DATA(2)
        RSEG    ICODE:CODE:NOROOT(2)
        PUBLIC  ?cstartup
        EXTERN  ?main

; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.


        CODE32
?cstartup


; Enable IRQ and FIQ interrupts
                mrs     r0,cpsr                             ; Original PSR value
                bic     r0,r0,#0xC0
                orr     r0,r0,#IRQ_MODE                     ; Set IRQ mode bits
                msr     cpsr_c,r0

; Add initialization nedded before setup of stackpointers here


; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
                mrs     r0,cpsr                             ; Original PSR value
                bic     r0,r0,#MODE_BITS                    ; Clear the mode bits
                orr     r0,r0,#IRQ_MODE                     ; Set IRQ mode bits
                msr     cpsr_c,r0                           ; Change the mode
                ldr     sp,=SFE(IRQ_STACK) & 0xFFFFFFF8     ; End of IRQ_STACK

                bic     r0,r0,#MODE_BITS                    ; Clear the mode bits
                orr     r0,r0,#FIQ_MODE                     ; Set System mode bits
                msr     cpsr_c,r0                           ; Change the mode
                ldr     sp,=SFE(FIQ_STACK) & 0xFFFFFFF8     ; End of FIQ_STACK

                bic     r0,r0,#MODE_BITS                    ; Clear the mode bits
                orr     r0,r0,#SYS_MODE                     ; Set System mode bits
                msr     cpsr_c,r0                           ; Change the mode
                ldr     sp,=SFE(CSTACK) & 0xFFFFFFF8        ; End of CSTACK

; Continue to ?main for more IAR specific system startup

                ldr     r0,=?main
                bx      r0

                LTORG

                ENDMOD


                END




